package mk.jug.academy.preconditions;

import mk.jug.academy.exception.BusinessException;
import mk.jug.academy.model.Course;
import mk.jug.academy.model.Lecturer;
import mk.jug.academy.model.Student;
import mk.jug.academy.model.status.CourseStatus;
import mk.jug.academy.model.status.LecturerStatus;
import mk.jug.academy.model.status.StudentStatus;

import org.springframework.util.Assert;


/**
 * Class separating the concerns of checking preconditions for
 * regarding {@link Course} processes.
 * 
 * It is usually a Precondition <-> Service pair.
 *
 * @author Ice.Penov
 */
public final class CoursePreconditions {

	/** No instantiation. Static usage only. */
	private CoursePreconditions() {;}
	
	public static void submitNewCourse(Course course) {
		Assert.notNull(course.getTitle(), PreconditionExceptions.MISSING_TITLE);
	}
	
	public static void hatchCourse(Course course) {
		if (!course.getStatus().equals(CourseStatus.HATCHING)) {
			throw new BusinessException(ErrorCodes.ERROR_COURSE_HATCHING_STATE);
		}
		Assert.notNull(course.getId(), PreconditionExceptions.ID_IS_NULL);
	}
	
	public static void startCourse(Course course) {
		if (!course.getStatus().equals(CourseStatus.AVAILABLE)) {
			throw new BusinessException(ErrorCodes.ERROR_COURSE_AVAILABLE_STATE);
		}
		Assert.notNull(course.getId(), PreconditionExceptions.ID_IS_NULL);
	}
	
	public static void finishCourse(Course course) {
		if (!course.getStatus().equals(CourseStatus.IN_PROGRESS)) {
			throw new BusinessException(ErrorCodes.ERROR_COURSE_IN_PROGRESS_STATE);
		}
		Assert.notNull(course.getId(), PreconditionExceptions.ID_IS_NULL);
	}
	
	public static void deactivateCourse(Course course) {
		if (!course.getStatus().equals(CourseStatus.AVAILABLE)) {
			throw new BusinessException(ErrorCodes.ERROR_COURSE_AVAILABLE_STATE);
		}
		Assert.notNull(course.getId(), PreconditionExceptions.ID_IS_NULL);
	}
	
	public static void assignLecturer(Course course, Lecturer lecturer) {
		Assert.notNull(lecturer.getId(), PreconditionExceptions.ID_IS_NULL);
		Assert.notNull(course.getId(), PreconditionExceptions.ID_IS_NULL);
		if (!course.getStatus().equals(CourseStatus.AVAILABLE)) {
			throw new BusinessException(ErrorCodes.ERROR_COURSE_LECTURER_ASSIGN);			
		}
		if (!lecturer.getStatus().equals(LecturerStatus.ACTIVE)) {
			throw new BusinessException(ErrorCodes.ERROR_LECTURER_ACTIVE_STATE);
		}
	}
	
	public static void removeLecturer(Course course, Lecturer lecturer) {
		Assert.notNull(lecturer.getId(), PreconditionExceptions.ID_IS_NULL);
		Assert.notNull(course.getId(), PreconditionExceptions.ID_IS_NULL);
		if (!course.getStatus().equals(CourseStatus.AVAILABLE)) {
			throw new BusinessException(ErrorCodes.ERROR_COURSE_LECTURER_ASSIGN);			
		}
		if (!lecturer.getStatus().equals(LecturerStatus.ACTIVE)) {
			throw new BusinessException(ErrorCodes.ERROR_LECTURER_ACTIVE_STATE);
		}
	}
	
	public static void assignStudent(Course course, Student student) {
		Assert.notNull(course.getId(), PreconditionExceptions.ID_IS_NULL);
		Assert.notNull(student.getId(), PreconditionExceptions.ID_IS_NULL);
		if (!course.getStatus().equals(CourseStatus.AVAILABLE)) {
			throw new BusinessException(ErrorCodes.ERROR_COURSE_STUDENT_ASSIGN);
		}
		if (!(student.getStatus().equals(StudentStatus.WAITING_FOR_ENROLLMENT) || student.getStatus().equals(StudentStatus.ENROLLED))) {
			throw new BusinessException(ErrorCodes.ERROR_STUDENT_WAITING_FOR_ENROLLMENT_STATE);
		}
	}
	
	public static void removeStudent(Course course, Student student) {
		Assert.notNull(student.getId(), PreconditionExceptions.ID_IS_NULL);
		Assert.notNull(course.getId(), PreconditionExceptions.ID_IS_NULL);
	}	
	
}
